// created by noellynch
// May 15, 2009

package com.sceneworker.util.swing.sourcecompletionpanel;

import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Collection;

import javax.swing.DefaultListModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListSelectionModel;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;

import com.myjavautils.swing.MJSwingUtils;

public class CompletionFrame extends JFrame implements KeyListener{

	private static final int NUDGE = 7;
	private		ICompletionHandler					mcl_completionHandler;
	private		Point								mcl_locOnScreen;
	private		JList								mcl_keyWordsList;
	private		Collection<ICodeCompletionKeyWord>	mcla_completionList;

	public	CompletionFrame(String str_keyWord, ICompletionHandler cl_handler, Collection<ICodeCompletionKeyWord> cla_completionList, int i_x, int i_y) {
		mcl_completionHandler = cl_handler;
		mcla_completionList = cla_completionList;

		mcl_locOnScreen = mcl_completionHandler.getTextComponent().getLocationOnScreen();

		setLocation(mcl_locOnScreen.x + i_x, mcl_locOnScreen.y + i_y);
		setSize(300, 200);
		setUndecorated(true);
		setAlwaysOnTop(true);

		if(!initialiseList(str_keyWord)) {
			return;
		}

		setVisible(true);

		toFront();

		addKeyListener(this);
		mcl_keyWordsList.addKeyListener(this);
	}

	public	boolean	keyWordInCompletionList(String str_keyWord) {
		for(ICodeCompletionKeyWord lstr_temp : mcla_completionList) {
			if(lstr_temp.getPart().indexOf(str_keyWord) != -1) {
				return true;
			}
		}
		
		return false;
	}
	
	private		boolean	initialiseList(String str_keyWord) {
		if(!keyWordInCompletionList(str_keyWord)) {
			return false;
		}

		JScrollPane		lcl_scrollPane = new JScrollPane();
		mcl_keyWordsList = new JList();
		mcl_keyWordsList.setModel(initialiseModel(str_keyWord));
		mcl_keyWordsList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		mcl_keyWordsList.setCellRenderer(new CodeCompletionListCellRenderer());
		lcl_scrollPane.setViewportView(mcl_keyWordsList);
		setContentPane(lcl_scrollPane);

		return true;
	}

	private		DefaultListModel	initialiseModel(String str_keyWord) {
		DefaultListModel		lcl_model = new DefaultListModel();
		
		for(ICodeCompletionKeyWord lstr_temp : mcla_completionList) {
			if(lstr_temp.getPart().indexOf(str_keyWord) != -1) {
				lcl_model.addElement(lstr_temp);
			}
		}

		return lcl_model;
	}

	public void keyPressed(KeyEvent e) {
		//System.out.println("pressed = " + e.getKeyChar() + " (code) " + e.getKeyCode());
		if(e.getKeyCode() == KeyEvent.VK_ESCAPE) {
			setVisible(false);
			return;
		}

		if((e.getKeyCode() == KeyEvent.VK_SHIFT) || (e.getKeyCode() == KeyEvent.VK_LEFT) || (e.getKeyCode() == KeyEvent.VK_RIGHT) 
				|| (e.getKeyCode() == KeyEvent.VK_UP) || (e.getKeyCode() == KeyEvent.VK_DOWN)) {
			return;
		}

		if(e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
			delete();
			updateListModel();
			return;
		}

		if(e.getKeyCode() == KeyEvent.VK_ENTER) {
			insertKeyWord();
			setVisible(false);
			return;
		}

		insert("" + e.getKeyChar());
		updateListModel();
	}

	private	void	insertKeyWord() {

		ICodeCompletionKeyWord	lcl_temp = (ICodeCompletionKeyWord)mcl_keyWordsList.getSelectedValue();

		if(lcl_temp == null) {
			return;
		}

		String	lstr_keyWord = MJSwingUtils.getKeyWordFromTextComponent(mcl_completionHandler.getTextComponent());

		//System.out.println("current keyword = " + lstr_keyWord);

		int				li_replaceStart = mcl_completionHandler.getTextComponent().getCaretPosition() - lstr_keyWord.length();
		int				li_replaceEnd = mcl_completionHandler.getTextComponent().getCaretPosition();
		
		mcl_completionHandler.replaceRange("", li_replaceStart, li_replaceEnd);
		mcl_completionHandler.insert(lcl_temp.getPart(), mcl_completionHandler.getTextComponent().getCaretPosition());

	}

	private	void	updateListModel() {
		String		lstr_keyWord = MJSwingUtils.getKeyWordFromTextComponent(mcl_completionHandler.getTextComponent());
		//System.out.println("keyword to update list model = " + lstr_keyWord);

		mcl_keyWordsList.setModel(initialiseModel(lstr_keyWord));
	}

	public void keyReleased(KeyEvent e) {
		//System.out.println("released = " + e.getKeyChar() + " (code) " + e.getKeyCode());

	}

	public void keyTyped(KeyEvent e) {
		//System.out.println("typed = " + e.getKeyChar() + " (code) " + e.getKeyCode());

	}

	private	void	insert(String str_in) {
		mcl_completionHandler.insert(str_in, mcl_completionHandler.getTextComponent().getCaretPosition());
		
		moveToCaret();
	}

	private	void	delete() {
		int				li_caret = mcl_completionHandler.getTextComponent().getCaretPosition();
		mcl_completionHandler.replaceRange("", li_caret - 1, li_caret);
		
		moveToCaret();
	}

	private	void	moveToCaret() {
		try {
			int				li_caret = mcl_completionHandler.getTextComponent().getCaretPosition();
			Rectangle		lcl_r = mcl_completionHandler.getTextComponent().modelToView(li_caret);
			setLocation(mcl_locOnScreen.x + lcl_r.x + 5, getLocation().y);
		} catch (BadLocationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public	interface	ICompletionHandler {
		void				insert(String str_s, int i_pos);
		void				replaceRange(String str_s, int i_start, int i_end);
		JTextComponent		getTextComponent();
	}
	
	private	class CodeCompletionListCellRenderer extends JLabel implements ListCellRenderer {
	     public CodeCompletionListCellRenderer() {
	         setOpaque(true);
	     }
	     public Component getListCellRendererComponent(
	         JList list,
	         Object value,
	         int index,
	         boolean isSelected,
	         boolean cellHasFocus)
	     {
	    	if (isSelected) {
	    	    setBackground(list.getSelectionBackground());
	    	    setForeground(list.getSelectionForeground());
	    	}
	    	else {
	    	    setBackground(list.getBackground());
	    	    setForeground(list.getForeground());
	    	}
	    	 
	         setText(((ICodeCompletionKeyWord)value).getRep());
	         
	         setEnabled(list.isEnabled());
	         setFont(list.getFont());

	         /*Border border = null;
	         if (cellHasFocus) {
	        	 if (isSelected) {
	        		 border = UIManager.getBorder("List.focusSelectedCellHighlightBorder");
	        	 }
	        	 if (border == null) {
	        		 border = UIManager.getBorder("List.focusCellHighlightBorder");
	        	 }
	         } else {
	        	 border = getNoFocusBorder();
	         }
	         setBorder(border);
	         */
	         
	         return this;
	     }
	 }

}
